package com.lgy.ms.service.service.base;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.lgy.ms.core.bean.RequestParams;
import com.lgy.ms.core.bean.ResponseParams;
import com.lgy.ms.core.bean.SessionInfo;
import com.lgy.ms.core.constant.RespCode;
import com.lgy.ms.core.dto.AppSessionDTO;
import com.lgy.ms.core.exception.AppException;
import com.lgy.ms.core.exception.BusinessException;
import com.lgy.ms.core.utils.DateUtil;
import com.lgy.ms.core.utils.StringUtil;
import com.lgy.ms.service.cache.AppSessionCache;
import com.lgy.ms.service.cache.SessionInfoCache;
import org.apache.commons.collections.MapUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.validation.BeanPropertyBindingResult;
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;

import javax.annotation.Resource;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author Gylin
 **/
public class AppBaseService {

    private Logger log = LoggerFactory.getLogger(AppBaseService.class);

    @Resource
    private Validator validator;
    @Resource
    private AppSessionCache appSessionCache;
    @Resource
    private SessionInfoCache sessionInfoCache;

    public ResponseParams<Object> buildResponseParams(RequestParams requestParams) {
        ResponseParams<Object> responseParams = new ResponseParams<>();
        responseParams.setSignType(requestParams.getSignType());
        responseParams.setEncryptType(requestParams.getEncryptType());
        responseParams.setTimestamp(DateUtil.formatDate(new Date(), "yyyyMMddHHmmss"));
        return responseParams;
    }

    protected ResponseParams<Object> finish(ResponseParams<Object> response, String code, String message) {
        response.setRespCode(code);
        response.setRespMsg(message);
        return response;
    }

    protected ResponseParams<Object> finish(ResponseParams<Object> response) {
        response.setRespCode(RespCode.SUCCESS_CODE);
        response.setRespMsg(RespCode.SUCCESS_CODE_MS);
        return response;
    }

    protected <T> T paramToObject(RequestParams requestParams, Class<T> clz) throws BusinessException {
        T t = null;
        try {
            if (requestParams.getParam() == null) {
                return clz.newInstance();
            }
            t = JSON.parseObject(JSON.toJSONString(requestParams.getParam()), clz);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new BusinessException(RespCode.ERR_PARAMETER_TYPE, RespCode.ERR_PARAMETER_TYPE_MS);
        }
        Errors errors = new BeanPropertyBindingResult(t, t.getClass().getName());
        validator.validate(t, errors);
        if (errors.hasErrors()) {
            String msg = errors.getFieldErrors().get(0).getDefaultMessage();
            throw new BusinessException(RespCode.ERR_VALIDATOR, msg);
        }
        return t;
    }

    protected BusinessException processException(Exception e, String errorMsg) {
        if (e instanceof BusinessException) {
            return (BusinessException) e;
        } else {
            log.error(e.getMessage(), e);
            if (errorMsg == null) {
                return new BusinessException(e.getMessage());
            } else {
                return new BusinessException(RespCode.ERROR_UNKOWN, errorMsg);
            }
        }
    }

    public void saveSessionInfo(SessionInfo sessionInfo) {
        sessionInfoCache.saveSessionInfo(sessionInfo.getUserId(), sessionInfo);
    }

    public SessionInfo setSessionInfoToLocalThreadParam() throws AppException {
        SessionInfo sessionInfo = null;
        RequestParams requestParams = AppRequestParam.get();
        if (requestParams == null) {
            return null;
        }
        String sessionId = requestParams.getSessionId();
        if (StrUtil.isNotEmpty(sessionId)) {
            AppSessionDTO appSessionDto = appSessionCache.getSession(sessionId);
            if (appSessionDto != null) {
                String userId = appSessionDto.getUserId();
                sessionInfo = sessionInfoCache.getSessionInfo(userId);
                if (sessionInfo != null) {
                    if (!sessionInfo.getSessionId().equals(appSessionDto.getSessionId())) {
                        throw new AppException(RespCode.ERROR_NOT_LOGIN, RespCode.ERROR_NOT_LOGIN_MSG);
                    }
                }
            }
        }
        log.info("sessionInfo:" + JSON.toJSONString(sessionInfo));
        AppRequestParam.setSessionInfo(sessionInfo);
        return sessionInfo;
    }

    protected Map<String, Integer> getPageParam(RequestParams requestParams) {
        Map<String, Integer> pageParam = requestParams.getPageParam();
        if (pageParam == null) {
            throw new BusinessException("分页参数未传");
        }
        Integer pageNum = pageParam.get("pageNum");
        Integer pageSize = pageParam.get("pageSize");
        if (pageNum == null || pageSize == null || pageSize == 0) {
            throw new BusinessException("分页参数未传");
        }
        return pageParam;
    }

    protected ResponseParams<Object> getPage(RequestParams requestParams, List list) {
        ResponseParams<Object> response = buildResponseParams(requestParams);
        Map<String, Integer> pageParam = getPageParam(requestParams);
        PageHelper.startPage(pageParam.get("pageNum"), pageParam.get("pageSize"));
        PageInfo pageInfo = new PageInfo(list);
        pageParam.put("pages", pageInfo.getPages());
        pageParam.put("total", (int) pageInfo.getTotal());
        response.setParam(pageInfo.getList());
        response.setPageParam(pageParam);
        return response;
    }

    protected Map<String, Object> getRequestParamMap() {
        RequestParams  requestParams = AppRequestParam.get();
        if (requestParams != null) {
            return (Map<String, Object>) requestParams.getParam();
        }
        return new HashMap<>(1);
    }

    protected void startPage(Map params) {
        int curPage = MapUtils.getIntValue(params, "currentPage");
        curPage = StringUtil.isEmpty(curPage) ? 0 : curPage;
        int pageSize = MapUtils.getIntValue(params, "pageSize");
        pageSize = StringUtil.isEmpty(pageSize) ? 0 : pageSize;
        PageHelper.startPage(curPage, pageSize);
    }
}
